package fun.coding.scopley;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class PathTreeImpl implements PathTree {

    @Override
    public Node insert(String path, Node head) {
        if(path == null || path.isEmpty()) 
            return head;
        
        String[] paths = path.split("/");
        int i = 0;
        ArrayList<Node> currList = new ArrayList<Node>();
        currList.add(head);
        
        System.out.println(Arrays.asList(paths));
        
        Node curr = new Node();
        List<Node> result = new LinkedList<Node>();
        while(i < paths.length) {
            if(isNodeInserted(currList, paths[i])) {
                System.out.println("node inserted, i:" + i + " path" + paths[i]);
                i++;
                curr = getFoundedNode(currList, paths[i]);
                currList.clear();
                currList.addAll(curr.getChildren());
            } else {
                result = buildNewTreePath(curr, paths, i);
                
                if(curr.getValue().isEmpty()) {
                    System.out.println("building a brand new tree");
                    
                    curr.setValue(result.get(0).getValue());
                    curr.setChildren(result.get(0).getChildren());
                    
                } else {
                    ArrayList<Node> child = new ArrayList<Node>();
                    child.add(result.get(0));
                    curr.setChildren(child);
                }

                for(int k = 0; k < result.size(); ++k) {
                    System.out.println("result list is " + result.get(k).getValue() + " child size:" + result.get(k).getChildren().size());
                }
                
                for(Node t : result.get(1).getChildren()) {
                    System.out.println("1 " + t.getValue());
                }
                
                break;
            }
        }
        printTree(result.get(0));    
        return curr;
    }

    private boolean isNodeInserted(ArrayList<Node> nodeList, String s) {
        for(Node n : nodeList) {
            if(n.getValue().equals(s))
                return true;
        }
        
        return false;
    }
    
    private Node getFoundedNode(ArrayList<Node> nodeList, String s) {
        for(Node n : nodeList) {
            if(n.getValue().equals(s))
                return n;
        }
        // Should never reach here.
        return new Node();
    }
    
    private List<Node> buildNewTreePath(Node node, String[] paths, int index) {
        System.out.println("building new tree, index:" + index);
        int i = index;
        List<Node> result = new LinkedList<Node>();
        
        while((i + 1) < paths.length) {
            ArrayList<Node> currChildren = new ArrayList<Node>();
            Node currNode = new Node();
            currNode.setValue(paths[i]);
            
            Node nextNode = new Node();
            nextNode.setValue(paths[i + 1]);
            
            currChildren.add(nextNode);
            currNode.setChildren(currChildren);
            
            result.add(currNode);
            i++;
        }
        
        // Add the last element
        ArrayList<Node> currChildren = new ArrayList<Node>();
        Node currNode = new Node();
        currNode.setValue(paths[i]);
        result.add(currNode);
     
        return result;
    }

    @Override
    public void printTree(Node head) {
        System.out.println("Printing queue with head: " + head.getValue());
        Queue<Node> queue = new LinkedList<Node>();
        
        if(!queue.offer(head))
            System.err.println("failed to insert");
        
        while(!queue.isEmpty()) {
            Node curr = queue.poll();
            System.out.println(curr.getValue());
            for(Node n : curr.getChildren()) {
                System.out.println("for current node " + curr.getValue() + " children " + n.getValue());
                if(!queue.offer(n)) 
                    System.err.println("failed to insert");
            }
        }
        
    }
}
